#define TKGRP_INFIX      (1 << 7)
#define TKGRP_UNARY      (1 << 8)
#define TKGRP_SYNTAX     (1 << 9)
#define TKGRP_ATOM       (1 << 10)
#define TKGRP_BRACKET    (1 << 11)
#define TKGRP_LBRACKET   (1 << 12)
#define TKGRP_RBRACKET   (1 << 13)
#define TKGRP_SPECIAL    (1 << 14)
#define TKGRP_KWEXP      (1 << 15)
#define TKGRP_LOWPRI     (1 << 16)
#define TKGRP_UNARY_PAT  (1 << 17)
#define TKGRP_HIPRI      (1 << 18)
#define TKGRP_NULLARY    (1 << 19)

/* Bitfield layout for token types:

      Bit
      0 - 6  ID Used to make token unique to its group
      Bits for token group follow...
      7      TKGRP_INFIX
      8      TKGRP_UNARY
      9      TKGRP_SYNTAX
      10     TKGRP_ATOM
      11     TKGRP_BRACKET
      12     TKGRP_LBRACKET
      13     TKGRP_RBRACKET
      14     TKGRP_SPECIAL
      15     TKGRP_KWEXP
      16     TKGRP_LOWPRI
      17     TKGRP_UNARY_PAT
*/

enum {
  TK_EOF = 0,

  // Special tokens
  TK_TEST    = TKGRP_SPECIAL | 1,
  TK_COMMENT = TKGRP_SPECIAL | 2,
  TK_NONE    = TKGRP_SPECIAL | 3,
  TK_NEWLINE = TKGRP_SPECIAL | 4,

  // Infix expression operators (all the same priority)
  TK_ADD    = TKGRP_INFIX | TKGRP_HIPRI | 1,
  TK_AND    = TKGRP_INFIX | TKGRP_HIPRI | 2,
  TK_ASSIGN = TKGRP_INFIX | TKGRP_HIPRI | 3,
  TK_CONS   = TKGRP_INFIX | TKGRP_HIPRI | 4,
  TK_OR     = TKGRP_INFIX | TKGRP_HIPRI | 5,
  TK_MUL    = TKGRP_INFIX | TKGRP_HIPRI | 6,
  TK_DIV    = TKGRP_INFIX | TKGRP_HIPRI | 7,
  TK_LT     = TKGRP_INFIX | TKGRP_HIPRI | 8,
  TK_LE     = TKGRP_INFIX | TKGRP_HIPRI | 9,
  TK_GT     = TKGRP_INFIX | TKGRP_HIPRI | 10,
  TK_GE     = TKGRP_INFIX | TKGRP_HIPRI | 11,
  TK_EQ     = TKGRP_INFIX | TKGRP_HIPRI | 12,
  TK_SUB    = TKGRP_INFIX | TKGRP_HIPRI | 13,

  // Unary expression operators
  TK_NOT    = TKGRP_UNARY | 1,
  TK_NEGATE = TKGRP_UNARY | 2,

  // Nullary expression operators
  TK_NULL = TKGRP_NULLARY | 1,

  // Unary pattern operators
  TK_REF = TKGRP_UNARY_PAT | 1,

  // atoms : symbols, varnames, numbers
  TK_ANONYMOUS_VAR = TKGRP_ATOM | 1,
  TK_VARNAME       = TKGRP_ATOM | 2,
  TK_NUMBER        = TKGRP_ATOM | 3,
  TK_SYMBOL        = TKGRP_ATOM | 4,

  // Brackets
  TK_L_CLOSURE_BRACK = TKGRP_BRACKET | TKGRP_LBRACKET | 1,
  TK_L_ROUND_BRACK   = TKGRP_BRACKET | TKGRP_LBRACKET | 2,
  TK_R_CLOSURE_BRACK = TKGRP_BRACKET | TKGRP_RBRACKET | 3,
  TK_R_ROUND_BRACK   = TKGRP_BRACKET | TKGRP_RBRACKET | 4,

  // Low-priority operators
  TK_SEQ          = TKGRP_INFIX | TKGRP_LOWPRI | 1,
  TK_TUPLE_APPEND = TKGRP_INFIX | TKGRP_LOWPRI | 2,

  // Keywords-expression symbols
  TK_ELSE  = TKGRP_KWEXP | 1,
  TK_EQUAL = TKGRP_KWEXP | 2,
  TK_IF    = TKGRP_KWEXP | 3,
  TK_LET   = TKGRP_KWEXP | 4,
  TK_THEN  = TKGRP_KWEXP | 5,

  // Symbol/keyword characters that aren't part of expression
  // syntax
  TK_RIGHT_ARROW = TKGRP_SYNTAX | 1,
  TK_PATTERN_ALT = TKGRP_SYNTAX | 2
};

typedef struct {
  int type;
  // TK_NUMBER
  double num;
  // TK_VARNAME or TK_SYMBOL
  char *name;
  // TK_TEST
  char c;
} TOKEN;

void tk_init(TOKEN *t);
void tk_free(TOKEN *t);
void tk_print(TOKEN *t);
void tk_str(TOKEN *t, char *str, size_t n);
int tk_next(GEN_READ *r, TOKEN *t);
